package com.jingbit.ai.helper;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.media.MediaScannerConnection;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.opengl.GLES20;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.widget.EditText;

import androidx.core.app.ActivityCompat;

import com.jingbit.ai.entities.AppInfo;
import com.jingbit.ai.entities.PhoneInfo;
import com.jingbit.ai.except.SDKExceptions;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 获取设备信息辅助类
 *
 * @author Wellsa
 */
@SuppressLint("NewApi")
public class DeviceHelper {

    private static final String TAG = "DeviceHelper";

    // 上网类型
    /**
     * 没有网络
     */
    public static final byte NETWORK_TYPE_INVALID = 0x0;
    /**
     * wifi网络
     */
    public static final byte NETWORK_TYPE_WIFI = 0x1;
    /**
     * 3G和3G以上网络，或统称为快速网络
     */
    public static final byte NETWORK_TYPE_3G = 0x2;
    /**
     * 2G网络
     */
    public static final byte NETWORK_TYPE_2G = 0x3;

    public static final String IMG_UNSPECIFIED = "image/*";

    public static final int DO_CANCEL_RESULT = 5; // 取消
    public static final int DO_CAMERA_RESULT = 6;// 拍照
    public static final int DO_GALLERY_RESULT = 7; // 相册
    public static final int DO_CROP_RESULT = 8;// 裁剪结果

    public static final int DO_QRCODE_RESULT = 9;// 裁剪结果

    public static int CROP_WIDTH = 100;// 设置裁剪图片的宽
    public static int CROP_HEIGHT = 100;// 设置裁剪图片的高

    // 拍照后的图片
    public static File pictureFile;

    @TargetApi(19)
    private static void setTranslucentStatus(Activity activity, boolean on) {
        Window win = activity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        View bodyView = win.getDecorView().findViewById(android.R.id.content);
        // Logger.log(TAG, "setTranslucentStatus", top,);
        if (bodyView != null) {
            int top = getStatusHeight(activity);
            bodyView.setPadding(0, top, 0, 0);
        }
        if (on) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
        }
        win.setAttributes(winParams);
    }

    public static String getPhoneno(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            return "";
        }
        return tm.getLine1Number();
    }

    /**
     * 获取imsi号
     *
     * @param context
     */
    public static String getImsi(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            return "";
        }
        String imsi = tm.getSubscriberId();
        if (imsi != null && !imsi.equals("")) {
            if (imsi.startsWith("46000") || imsi.startsWith("46002")) {
                // 因为移动网络编号46000下的IMSI已经用完，所以虚拟了一个46002编号，134/159号段使用了此编号
                //
                return "中国移动";
            } else if (imsi.startsWith("46001")) {
                // 中国联通
                return "中国联通";
            } else if (imsi.startsWith("46003")) {
                // 中国电信
                return "中国电信";
            }
        }
        return imsi;
    }

    /**
     * 双卡双待手机获取imsi号， 能获取2个
     *
     * @param context
     * @param cardID  card1:0; card2:1
     * @return
     */
    public static String getDoubleImsi(Context context, int cardID) {
        String imsi = null;
        if (context == null) {
            return null;
        }
        if (cardID < 0 || cardID > 1) {
            return null;
        }
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

        try {
            Class<?> mLoadClass = Class.forName("android.telephony.TelephonyManager");

            Class<?>[] parameter = new Class[1];
            parameter[0] = int.class;
            Method getSubscriberIdGemini = mLoadClass.getMethod("getSubscriberIdGemini", parameter);

            Object[] obParameter = new Object[1];

            Object ob_imsi = null;

            obParameter[0] = cardID;
            ob_imsi = getSubscriberIdGemini.invoke(telephonyManager, obParameter);

            if (ob_imsi != null) {
                imsi = ob_imsi.toString();
            }

        } catch (Exception e) {
            e.printStackTrace();
            Logger.log(TAG, "getDoubleImsi err" + e.toString());
        }
        return imsi;
    }

    /**
     * 获取imei号(需要 READ_PHONE_STATE权限)
     *
     * @return
     */
    public static String getImei(Context context) {
        String imei = "000000000000000";
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                return "";
            }
            imei = tm.getDeviceId();
        } catch (Exception e) {
            Logger.log(TAG, "getImei err" + e.toString());
        }
        return imei;
    }

    /**
     * Returns the MCC+MNC (mobile country code + mobile network code) of the
     * provider of the SIM. 5 or 6 decimal digits.
     * 获取SIM卡提供的移动国家码和移动网络码.5或6位的十进制数字. SIM卡的状态必须是
     * SIM_STATE_READY(使用getSimState()判断).
     *
     * @param context
     * @return
     */
    public static String getSimOperator(Context context) {
        String operator = "";
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            operator = tm.getSimOperator();// String
        } catch (Exception e) {
            Logger.log(TAG, "getSimOperator err" + e.toString());
        }
        return operator;
    }

    /**
     * 服务商名称： 例如：中国移动、联通 SIM卡的状态必须是 SIM_STATE_READY(使用getSimState()判断).
     *
     * @param context
     * @return
     */
    public static String getSimOperatorName(Context context) {
        String operatorName = "";
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
                operatorName = tm.getSimOperatorName();// String
            }
        } catch (Exception e) {
            Logger.log(TAG, "getSimOperatorName err" + e.toString());
        }
        return operatorName;
    }

    /**
     * 获取手机厂商名称
     *
     * @return
     */
    public static String getProduct() {
        return Build.PRODUCT;
    }

    /**
     * 获取手机厂商名称
     *
     * @return
     */
    public static String getModel() {
        return Build.MODEL;
    }

    /**
     * 获取手机厂商名称
     *
     * @return
     */
    public static String getBrand() {
        return Build.BRAND;
    }

    /**
     * 获取程序版本号
     *
     * @return
     */
    public static int getVersionCode(Context context) {
        // 获取packagemanager的实例
        PackageManager packageManager = context.getPackageManager();
        // getPackageName()是你当前类的包名，0代表是获取版本信息
        PackageInfo packInfo = null;
        try {
            packInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return packInfo.versionCode;
    }

    /**
     * 获取程序版本名
     *
     * @return
     */
    public static String getVersionName(Context context) {
        // 获取packagemanager的实例
        PackageManager packageManager = context.getPackageManager();
        // getPackageName()是你当前类的包名，0代表是获取版本信息
        PackageInfo packInfo = null;
        try {
            packInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return packInfo.versionName;
    }

    /**
     * 获取系统版本号
     *
     * @return
     */
    public static int getSysVersionCode() {
        return Build.VERSION.SDK_INT;
    }

    /**
     * 获取系统版本名
     *
     * @return
     */
    public static String getSysVersionName() {
        return Build.VERSION.RELEASE;
    }

    /**
     * 获取MAC地址
     *
     * @param context
     * @return
     */
    public static String getMacAddr(Context context) {
        // 在wifi未开启状态下，仍然可以获取MAC地址，但是IP地址必须在已连接状态下否则为0
        String macAddress = null;
        WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = (null == wifiMgr ? null : wifiMgr.getConnectionInfo());
        if (null != info) {
            macAddress = info.getMacAddress();
        }
        if (macAddress == null) {
            macAddress = "";
        }
        return macAddress;
    }

    /**
     * 获取BSSID地址
     *
     * @param context
     * @return
     */
    public static String getBSSID(Context context) {
        // 在wifi未开启状态下，仍然可以获取MAC地址，但是IP地址必须在已连接状态下否则为0
        String BSSID = null;
        WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = (null == wifiMgr ? null : wifiMgr.getConnectionInfo());
        if (null != info) {
            BSSID = info.getBSSID();
        }
        if (BSSID == null) {
            BSSID = "";
        }
        return BSSID;
    }

    /**
     * 获取SSID地址
     *
     * @param context
     * @return
     */
    public static String getSSID(Context context) {
        // 在wifi未开启状态下，仍然可以获取MAC地址，但是IP地址必须在已连接状态下否则为0
        String SSID = null;
        WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = (null == wifiMgr ? null : wifiMgr.getConnectionInfo());
        if (null != info) {
            SSID = info.getSSID();
        }
        if (SSID == null) {
            SSID = "";
        }
        return SSID;
    }

    public static String getIpAddress(Context context) {
        NetworkInfo info = ((ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                try {
                    //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
                    for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                        NetworkInterface intf = en.nextElement();
                        for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                            InetAddress inetAddress = enumIpAddr.nextElement();
                            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }

            } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
                return ipAddress;
            }
        } else {
            //当前无网络连接,请在设置中打开网络
        }
        return null;
    }

    /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    public static String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }

    public static PhoneInfo getPhoneInfo(Context context) {
        PhoneInfo phoneInfo = new PhoneInfo();
        phoneInfo.setImsi(getImsi(context));
        phoneInfo.setImei(getImei(context));
        phoneInfo.setMac(getMacAddr(context));
        phoneInfo.setIpAddr(getIpAddress(context));
        phoneInfo.setBSSID(getBSSID(context));
        phoneInfo.setSSID(getSSID(context));
        phoneInfo.setBrand(getBrand());
        phoneInfo.setProduct(getProduct());
        return phoneInfo;
    }

    public static String getCpuName() {
        FileReader fr = null;
        BufferedReader br = null;
        String[] array = null;
        try {
            fr = new FileReader("/proc/cpuinfo");
            br = new BufferedReader(fr);
            String text = br.readLine();
            array = text.split(":\\s+", 2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (fr != null) {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (array != null && array.length >= 2) {
            return array[1];
        }
        return null;
    }

    /**
     * Gets the number of cores available in this device, across all processors.
     * Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu"
     *
     * @return The number of cores, or 1 if failed to get result
     */
    public static int getCpuCount() {
        // Private Class to display only CPU devices in the directory listing
        class CpuFilter implements FileFilter {
            @Override
            public boolean accept(File pathname) {
                // Check if filename is "cpu", followed by a single digit number
                if (Pattern.matches("cpu[0-9]", pathname.getName())) {
                    return true;
                }
                return false;
            }
        }

        try {
            // Get directory containing CPU info
            File dir = new File("/sys/devices/system/cpu/");
            // Filter to only list the devices we care about
            File[] files = dir.listFiles(new CpuFilter());
            // Return the number of cores (virtual CPU devices)
            return files.length;
        } catch (Exception e) {
            // Default to return 1 core
            return 1;
        }
    }

    /**
     * 获取网络状态，wifi,3g,2g,无网络。
     *
     * @param context 上下文
     * @return byte 网络状态 {@link #NETWORK_TYPE_WIFI}, {@link #NETWORK_TYPE_3G},
     * {@link #NETWORK_TYPE_2G}, {@link #NETWORK_TYPE_INVALID}
     */
    public static byte getNetWorkType(Context context) {
        byte mNetWorkType = NETWORK_TYPE_INVALID;
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            int nType = networkInfo.getType();
            if (nType == ConnectivityManager.TYPE_WIFI) {
                mNetWorkType = NETWORK_TYPE_WIFI;
            } else if (nType == ConnectivityManager.TYPE_MOBILE) {
                // String proxyHost =
                // android.net.Proxy.getDefaultHost();//TextUtils.isEmpty(proxyHost)=false为wap网络
                mNetWorkType = (isFastMobileNetwork(context) ? NETWORK_TYPE_3G : NETWORK_TYPE_2G);
            }
        } else {
            mNetWorkType = NETWORK_TYPE_INVALID;
        }

        return mNetWorkType;
    }

    /**
     * 判断是2G网络还是3G以上网络 false:2G网络;true:3G以上网络
     */
    private static boolean isFastMobileNetwork(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        switch (telephonyManager.getNetworkType()) {
            case TelephonyManager.NETWORK_TYPE_UNKNOWN:// 0
                return false;
            case TelephonyManager.NETWORK_TYPE_GPRS:// 1
                return false; // ~ 100 kbps
            case TelephonyManager.NETWORK_TYPE_EDGE:// 2
                return false; // ~ 50-100 kbps
            case TelephonyManager.NETWORK_TYPE_UMTS:// 3
                return true; // ~ 400-7000 kbps
            case TelephonyManager.NETWORK_TYPE_CDMA:// 4
                return false; // ~ 14-64 kbps
            case TelephonyManager.NETWORK_TYPE_EVDO_0:// 5
                return true; // ~ 400-1000 kbps
            case TelephonyManager.NETWORK_TYPE_EVDO_A:// 6
                return true; // ~ 600-1400 kbps
            case TelephonyManager.NETWORK_TYPE_1xRTT:// 7
                return false; // ~ 50-100 kbps
            case TelephonyManager.NETWORK_TYPE_HSDPA:// 8
                return true; // ~ 2-14 Mbps
            case TelephonyManager.NETWORK_TYPE_HSUPA:// 9
                return true; // ~ 1-23 Mbps
            case TelephonyManager.NETWORK_TYPE_HSPA:// 10
                return true; // ~ 700-1700 kbps
            case TelephonyManager.NETWORK_TYPE_IDEN:// 11
                return false; // ~25 kbps
            // SDK4.0才支持以下接口
            case 12:// TelephonyManager.NETWORK_TYPE_EVDO_B://12
                return true; // ~ 5 Mbps
            case 13:// TelephonyManager.NETWORK_TYPE_LTE://13
                return true; // ~ 10+ Mbps
            case 14:// TelephonyManager.NETWORK_TYPE_EHRPD://14
                return true; // ~ 1-2 Mbps
            case 15:// TelephonyManager.NETWORK_TYPE_HSPAP://15
                return true; // ~ 10-20 Mbps
            default:
                return false;
        }
    }

    public static Display getDisplay(Activity context) {
        return context.getWindowManager().getDefaultDisplay();
    }

    /**
     * 是否触碰了Home键
     *
     * @param activity
     * @return
     */
    public static boolean onHome(Activity activity) {
        List<String> homes = getCurrentPkg(activity);
        ActivityManager mActivityManager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
        return homes.contains(rti.get(0).topActivity.getPackageName());
    }

    private static List<String> getCurrentPkg(Activity activity) {
        List<String> packages = new ArrayList<String>();
        PackageManager packageManager = activity.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo info : resolveInfo) {
            packages.add(info.activityInfo.packageName);
        }
        return packages;
    }

    /**
     * 判断手机号是否正确
     *
     * @param phone
     * @return
     */
    public static boolean checkPhone(String phone) {
        if (phone.length() == 11) {
            Pattern pattern1 = Pattern.compile("^13\\d{9}||15[8,9]\\d{8}$");
            Pattern pattern2 = Pattern.compile("^15\\d{9}||15[8,9]\\d{8}$");
            Pattern pattern3 = Pattern.compile("^18\\d{9}||15[8,9]\\d{8}$");
            Pattern pattern4 = Pattern.compile("^17\\d{9}||15[8,9]\\d{8}$");
            Matcher matcher1 = pattern1.matcher(phone);
            Matcher matcher2 = pattern2.matcher(phone);
            Matcher matcher3 = pattern3.matcher(phone);
            Matcher matcher4 = pattern4.matcher(phone);
            if (matcher1.matches() || matcher2.matches() || matcher3.matches() || matcher4.matches()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断邮箱是否正确
     *
     * @param email
     * @return
     */
    public static boolean checkEmail(String email) {
        String str = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";
        Pattern p = Pattern.compile(str);
        Matcher m = p.matcher(email);
        return m.matches();
    }

    /**
     * 发送短信
     *
     * @param smsBody
     */
    public static void sendSms(Activity activity, String smsBody) {
        Uri smsToUri = Uri.parse("smsto:");
        Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
        intent.putExtra("sms_body", smsBody);
        activity.startActivity(intent);
    }

    /**
     * 指定发送短信
     *
     * @param smsBody
     */

    public static void sendSms(Activity activity, String user, String smsBody) {
        Uri smsToUri;
        if (user == null || user.equals("")) {
            smsToUri = Uri.parse("smsto:");
        } else {
            smsToUri = Uri.parse("smsto:" + user);
        }
        Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
        intent.putExtra("sms_body", smsBody);
        activity.startActivity(intent);
    }

    /**
     * 发送邮件
     *
     * @param title
     * @param content
     */
    public static void sendEmail(Activity activity, String title, String content) {
        Uri uri = Uri.parse("mailto:");
        Intent data = new Intent(Intent.ACTION_SENDTO, uri);
        data.putExtra(Intent.EXTRA_SUBJECT, title);
        data.putExtra(Intent.EXTRA_TEXT, content);
        activity.startActivity(data);
    }

    /**
     * 指定发送邮件
     *
     * @param email
     * @param title
     * @param content
     */
    public static void sendEmail(Activity activity, String email, String title, String content) {
        Intent data = new Intent(Intent.ACTION_SENDTO);
        if (email == null || email.equals("")) {
            sendEmail(activity, title, content);
            return;
        }
        data.setData(Uri.parse("mailto:" + email));
        data.putExtra(Intent.EXTRA_SUBJECT, title);
        data.putExtra(Intent.EXTRA_TEXT, content);
        activity.startActivity(data);
    }

    /**
     * 复制
     *
     * @param content
     */
    @SuppressWarnings("deprecation")
    public static void doCopy(Context context, String content) {
        ClipboardManager cbm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        cbm.setText(content.trim());
    }

    /**
     * 粘贴
     *
     * @param context
     * @return
     */
    @SuppressWarnings("deprecation")
    public static String doPaste(Context context) {
        // 得到剪贴板管理器
        ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        return cmb.getText().toString().trim();
    }

    /**
     * 打开网络设置界面
     */
    public static void openSetting(Activity activity) {
        Intent intent = new Intent("/");
        ComponentName cm = new ComponentName("com.android.settings", "com.android.settings.WirelessSettings");
        intent.setComponent(cm);
        intent.setAction("android.intent.action.VIEW");
        activity.startActivityForResult(intent, 0);
    }

    public static void openBrowser(Activity activity, String uri) {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.VIEW");
        intent.setData(Uri.parse(uri));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//		intent.setClassName(packageName,className);
        activity.startActivity(intent);
    }

    /**
     * 打开系统视频播放器
     */
    public static void openVideo(Activity activity, String filePath) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("file://" + filePath), "video/*");
        activity.startActivity(intent);
    }

    /**
     * 打开系统音乐播放器
     */
    public static void openAudio(Activity activity, String filePath) {
        Intent it = new Intent(Intent.ACTION_VIEW);
        it.setDataAndType(Uri.parse("file://" + filePath), "audio/*");
        activity.startActivity(it);
    }

    /**
     * 打开图库
     *
     * @param activity
     */
    public static void openGallery(Activity activity, boolean isMulti) {
        // Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        // IMG_UNSPECIFIED);
    }

    /**
     * 打开图库
     *
     * @param activity
     */
    public static void openGallery(Activity activity, int requestCode) {
        // Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        // IMG_UNSPECIFIED);
//		Intent intent = new Intent(activity, ImageSelectActivity.class);
//		intent.putExtra("isMulti", true);
//		activity.startActivityForResult(intent, requestCode);
    }

    /**
     * 打开照相机
     *
     * @param activity
     */
    public static void openCamera(Activity activity) {
        String fileName = FileHelper.getFileName(".png");
        pictureFile = new File(FileHelper.getDiskCachePath(FileHelper.IMAGE_CACHE_DIR), fileName);
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pictureFile));
        activity.startActivityForResult(intent, DO_CAMERA_RESULT);
    }

    /**
     * intent.setType(“image/*”);
     * intent.setType(“audio/*”); //选择音频
     * intent.setType(“video/*”); //选择视频 （mp4 3gp 是android支持的视频格式）
     * intent.setType(“video/*;image/*”);//同时选择视频和图片
     *
     * @param activity
     */
    public static void openFileBrowser(Activity activity) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("*/*");//设置类型，我这里是任意类型，任意后缀的可以这样写。
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        activity.startActivityForResult(intent, 1);
    }


    /**
     * 打卡软键盘
     *
     * @param mEditText 输入框
     * @param mContext  上下文
     */
    public static void openKeybord(EditText mEditText, Context mContext) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(mEditText, InputMethodManager.RESULT_SHOWN);
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }

    /**
     * 关闭软键盘
     *
     * @param mEditText 输入框
     * @param mContext  上下文
     */
    public static void hideKeybord(EditText mEditText, Context mContext) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);

        imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }

    /**
     * 判断是否有卡在运行
     */
    public static boolean isMountting() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    public static int computePageCount(int totalCount, int pageSize) {
        int pageCount = (int) Math.ceil(totalCount / (double) pageSize);
        return (pageCount == 0) ? 1 : pageCount;
    }

    /**
     * 刷新媒体数据（应用拍照或摄像后调用）
     *
     * @param context
     */
    public static void doMediaScanner(Context context) {
        if (getSysVersionCode() < 19)
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
                    Uri.parse("file://" + Environment.getExternalStorageDirectory())));
        else
            MediaScannerConnection.scanFile(context,
                    new String[]{Environment.getExternalStorageDirectory().getPath()}, null, null);
    }

    /**
     * whether context is system application
     *
     * @param context
     * @return
     */
    public static boolean isSysApplication(Context context) {
        if (context == null) {
            return false;
        }

        return isSysApplication(context, context.getPackageName());
    }

    /**
     * whether packageName is system application
     *
     * @param context
     * @param pkgName
     * @return
     */
    public static boolean isSysApplication(Context context, String pkgName) {
        if (context == null) {
            return false;
        }

        return isSystemApplication(context.getPackageManager(), pkgName);
    }

    /**
     * whether packageName is system application
     *
     * @param packageManager
     * @param packageName
     * @return <ul>
     *         <li>if packageManager is null, return false</li>
     *         <li>if package name is null or is empty, return false</li>
     *         <li>if package name not exit, return false</li>
     *         <li>if package name exit, but not system app, return false</li>
     *         <li>else return true</li>
     *         </ul>
     */
    public static boolean isSystemApplication(PackageManager packageManager, String packageName) {
        if (packageManager == null || packageName == null || packageName.length() == 0) {
            return false;
        }

        try {
            ApplicationInfo app = packageManager.getApplicationInfo(packageName, 0);
            return (app != null && (app.flags & ApplicationInfo.FLAG_SYSTEM) > 0);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获得状态栏的高度
     *
     * @param context
     * @return
     */
    public static int getStatusHeight(Context context) {

        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }

    /**
     * 获取当前屏幕截图，包含状态栏
     *
     * @param activity
     * @return
     */
    public static Bitmap snapShotWithStatusBar(Activity activity) {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, 0, CURR_WIDTH, CURR_HEIGHT);
        view.destroyDrawingCache();
        return bp;

    }

    /**
     * 获取当前屏幕截图，不包含状态栏
     *
     * @param activity
     * @return
     */
    public static Bitmap snapShotWithoutStatusBar(Activity activity) {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;

        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, CURR_WIDTH, CURR_HEIGHT - statusBarHeight);
        view.destroyDrawingCache();
        return bp;

    }

    private static final float DEFAULT_WIDTH = 480;
    private static final float DEFAULT_HEIGHT = 800;
    public static int CURR_WIDTH;
    public static int CURR_HEIGHT;

    /**
     * 根据传的宽度确定适合当前手机的图片宽
     *
     * @param width
     * @return
     */
    public static int getFitWidth(int width) {
        return (int) ((CURR_WIDTH / DEFAULT_WIDTH) * width);
    }

    public static int getFitHeight(int height) {
        return (int) ((CURR_HEIGHT / DEFAULT_HEIGHT) * height);
    }

    /**
     * dp转px
     *
     * @param context
     * @param dpVal
     * @return
     */
    public static int dp2px(Context context, float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
                context.getResources().getDisplayMetrics());
    }

    /**
     * sp转px
     *
     * @param context
     * @return
     */
    public static int sp2px(Context context, float spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
                context.getResources().getDisplayMetrics());
    }

    /**
     * px转dp
     *
     * @param context
     * @param pxVal
     * @return
     */
    public static float px2dp(Context context, float pxVal) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (pxVal / scale);
    }

    /**
     * px转sp
     *
     * @param context
     * @param pxVal
     * @return
     */
    public static float px2sp(Context context, float pxVal) {
        return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
    }

    public static String getMetaValue(Context context, String metaName) {
        try {
            ApplicationInfo appInfo = context.getPackageManager()
                    .getApplicationInfo(context.getPackageName(),
                            PackageManager.GET_META_DATA);
            return appInfo.metaData.getString(metaName);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return "";
    }

    // 全部程序包
    public static List<AppInfo> queryFilterAppInfo(Context context) {
        List<AppInfo> appInfos = new ArrayList<AppInfo>();
        PackageManager pm = context.getPackageManager();
        // 查询所有已经安装的应用程序
        List<ApplicationInfo> listAppcations = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);// GET_UNINSTALLED_PACKAGES代表已删除，但还有安装目录的
        for (ApplicationInfo app : listAppcations) {
            AppInfo appInfo = new AppInfo();
            appInfo.setLabel((String) app.loadLabel(pm));
//			appInfo.setIcon(app.loadIcon(pm));
//			appInfo.setPkgName(app.processName);
            appInfos.add(appInfo);
        }
        return appInfos;
    }

    // 获得所有系统的
    public static List<AppInfo> querySysAppInfo(Context context) {
        List<AppInfo> appInfos = new ArrayList<AppInfo>();
        PackageManager pm = context.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        // 通过查询，获得所有ResolveInfo对象.
        List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);

        for (ResolveInfo reInfo : resolveInfos) {
            String actName = reInfo.activityInfo.name; // 获得该应用程序的启动Activity的name
            String pkgName = reInfo.activityInfo.packageName; // 获得应用程序的包名
            String label = (String) reInfo.loadLabel(pm); // 获得应用程序的Label
            Drawable icon = reInfo.loadIcon(pm); // 获得应用程序图标
            AppInfo appInfo = new AppInfo();
//			appInfo.setIcon(icon);
            appInfo.setActName(actName);
            appInfo.setPkgName(pkgName);
            appInfo.setLabel(label);
        }
        return appInfos;
    }

    // 最简单的方法
    public static boolean appIsInstalled(Context context, String packageName) {
        try {
            PackageManager pm = context.getPackageManager();
            pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
            System.out.println("已安装" + packageName);
        } catch (NameNotFoundException e) {
            System.out.println("没有安装" + packageName);
            return false;
        }
        return true;
    }

    // 直接启动方法
    public void srartApp(Context context, String packageName) {
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
        if (intent != null)
            // 已安装包 直接启动
            context.startActivity(intent);
    }

    /**
     * @param root       最外层布局，需要调整的布局
     * @param scrollView 被键盘遮挡的scrollToView，滚动root,使scrollToView在root可视区域的底部
     */
    public static void controlKeyboard(final View root, final View scrollView) {
        final Rect operateRect = new Rect();
        root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Logger.log("controlKeyboardLayout", operateRect);
                if (operateRect != null) {
                    // 键盘隐藏
                    root.scrollTo(0, 0);
                }
                // 获取root在窗体的可视区域
                root.getWindowVisibleDisplayFrame(operateRect);
                // 获取root在窗体的不可视区域高度(被其他View遮挡的区域高度)
                int rootInvisibleHeight = root.getRootView().getHeight() - operateRect.bottom;
                // 若不可视区域高度大于100，则键盘显示
                // Logger.log("controlKeyboardLayout~",
                // operateRect.toString() + " / "
                // + rootInvisibleHeight);
                if (rootInvisibleHeight > 80) {
                    int[] location = new int[2];
                    // 获取scrollToView在窗体的坐标
                    scrollView.getLocationInWindow(location);
                    // 计算root滚动高度，使scrollToView在可见区域
                    int srollHeight = (location[1] + scrollView.getHeight()) - operateRect.bottom;
                    // Logger.log("controlKeyboardLayout~~",
                    // srollHeight);
                    root.scrollTo(0, srollHeight);
                } else {
                    // 键盘隐藏
                    root.scrollTo(0, 0);
                    // Logger.log("controlKeyboardLayout hidden",
                    // operateRect);
                }
            }
        });
    }

    /**
     * 将cookie同步到WebView
     *
     * @param url    WebView要加载的url
     * @param cookie 要同步的cookie
     * @return true 同步cookie成功，false同步cookie失败
     * @Author JPH
     */
    public static boolean setCookie(Context context, String url, String cookie) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            CookieSyncManager syncManager = CookieSyncManager.createInstance(context);
        }
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setCookie(url, cookie);//如果没有特殊需求，这里只需要将session id以"key=value"形式作为cookie即可
        String newCookie = cookieManager.getCookie(url);
        return TextUtils.isEmpty(newCookie) ? false : true;
    }

    /**
     * 获取android设备中全部app名称和应用包名
     * */
    public static void getAllAppNames(Context ctx){
        ArrayList customApps = new ArrayList<PackageInfo>(); // 普通应用程序列表
        ArrayList systemApps = new ArrayList<PackageInfo>(); // 系统应用程序列表
        // 得到PackageManager对象
        PackageManager pm=ctx.getPackageManager();
//        获取到所有安装了的应用程序的信息，包括那些卸载了的，但没有清除数据的应用程序
        List<PackageInfo> appList=pm.getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES);

        int j=0;

        for (PackageInfo packageInfo : appList) {
            // 列出普通应用
            if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
                customApps.add(packageInfo);
            }
            // 列出系统应用，总是感觉这里设计的有问题，希望高手指点
            if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) {
                systemApps.add(packageInfo);
            }
            //得到手机上已经安装的应用的名字,即在AndriodMainfest.xml中的app_name。
            String appName=packageInfo.applicationInfo.loadLabel(ctx.getPackageManager()).toString();
            //得到手机上已经安装的应用的图标,即在AndriodMainfest.xml中的icon。
            Drawable drawable = packageInfo.applicationInfo.loadIcon(ctx.getPackageManager());
            //得到应用所在包的名字,即在AndriodMainfest.xml中的package的值。
            String packageName=packageInfo.packageName;
            Log.e("=======aaa", "应用的名字:"+appName);
            Log.e("=======bbbb", "应用的包名字:"+packageName);
            // 禁用
            // pm.setApplicationEnabledSetting(packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);

            j++;
        }
        Log.e("========cccccc", "应用的总个数:"+j);
        Log.e("========eeeeee", "普通应用总个数:"+customApps.size());
        Log.e("========dddddd", "系统应用总个数:"+systemApps.size());
    }

    /**
     *
     * 不可用状态：COMPONENT_ENABLED_STATE_DISABLED
     * 可用状态：COMPONENT_ENABLED_STATE_ENABLED
     * 默认状态：COMPONENT_ENABLED_STATE_DEFAULT
     *
     * */
    private static void hidenApp(Context ctx,String pkgName,String clsName){
        PackageManager packageManager = ctx.getPackageManager();
        ComponentName componentName = new ComponentName(pkgName,clsName);
        int res = packageManager.getComponentEnabledSetting(componentName);
        if (res == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                || res == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
            // 隐藏应用图标
            packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                    PackageManager.DONT_KILL_APP);
        }
    }

    /**
     *
     * 不可用状态：COMPONENT_ENABLED_STATE_DISABLED
     * 可用状态：COMPONENT_ENABLED_STATE_ENABLED
     * 默认状态：COMPONENT_ENABLED_STATE_DEFAULT
     *
     * */
    private static void showApp(Context ctx,String pkgName,String clsName){
        PackageManager packageManager = ctx.getPackageManager();
        ComponentName componentName = new ComponentName(pkgName, clsName);
        int res = packageManager.getComponentEnabledSetting(componentName);
        if (res == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
            // 显示应用图标
            packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                    PackageManager.DONT_KILL_APP);
        }
    }

    public static void killApp(Context ctx,String pkgName){
        ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
        activityManager.killBackgroundProcesses(pkgName);
    }

    public static void recursiveCreateDirectories(String fileDir) {
        String[] fileDirs = fileDir.split("\\/");
        String topPath = "";
        for (int i = 0; i < fileDirs.length; i++) {
            topPath += "/" + fileDirs[i];
            File file = new File(topPath);
            if (file.exists()) {
                continue;
            } else {
                file.mkdir();
            }
        }
    }

    public static void copyAssets(Context ctx, String nnFileName) throws
            SDKExceptions.NoSDCardPermission,
            SDKExceptions.MissingModleFileInAssetFolder {
        AssetManager assetManager = ctx.getAssets();
        InputStream is = null;
        try {
            is = assetManager.open(nnFileName);
        } catch (IOException ex) {
            // file does not exist
            throw new SDKExceptions.MissingModleFileInAssetFolder();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // check SD card power
        int perm = ctx.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE");
        if (!(perm == PackageManager.PERMISSION_GRANTED)) {
            // Log.e(TAG, "please grant permission for SD storeage.");
            throw new SDKExceptions.NoSDCardPermission();
        }
        // check whether file on SD card
        File fileInSD = new File(ctx.getExternalFilesDir(null), nnFileName);

        if (fileInSD.exists()) {
            Log.d("debug===", "NN model on SD card " + fileInSD);
            return;
        }
        // copy file to app
        InputStream in = null;
        OutputStream out = null;
        try {
            in = assetManager.open(nnFileName);
            File outFile = new File(ctx.getExternalFilesDir(null), nnFileName);
            if(!outFile.getParentFile().exists()){
                outFile.getParentFile().mkdirs();
            }
            out = new FileOutputStream(outFile);
            byte[] buffer = new byte[1024];
            int read;
            while ((read = in.read(buffer)) != -1) {
                out.write(buffer, 0, read);
            }
        } catch (IOException e) {
            Log.e("tag", "Failed to copy asset file: " + nnFileName, e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                }
            }
        }
    }

    public static void copyFileFromAssets(Context appCtx, String srcPath, String dstPath) {
        if (srcPath.isEmpty() || dstPath.isEmpty()) {
            return;
        }
        String dstDir = dstPath.substring(0, dstPath.lastIndexOf('/'));
        if (dstDir.length() > 0) {
            recursiveCreateDirectories(dstDir);
        }
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new BufferedInputStream(appCtx.getAssets().open(srcPath));
            os = new BufferedOutputStream(new FileOutputStream(new File(dstPath)));
            byte[] buffer = new byte[1024];
            int length = 0;
            while ((length = is.read(buffer)) != -1) {
                os.write(buffer, 0, length);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                os.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void copyDirectoryFromAssets(Context appCtx, String srcDir, String dstDir) {
        if (srcDir.isEmpty() || dstDir.isEmpty()) {
            return;
        }
        try {
            if (!new File(dstDir).exists()) {
                new File(dstDir).mkdirs();
            }
            for (String fileName : appCtx.getAssets().list(srcDir)) {
                String srcSubPath = srcDir + File.separator + fileName;
                String dstSubPath = dstDir + File.separator + fileName;
                if (new File(srcSubPath).isDirectory()) {
                    copyDirectoryFromAssets(appCtx, srcSubPath, dstSubPath);
                } else {
                    copyFileFromAssets(appCtx, srcSubPath, dstSubPath);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static float[] parseFloatsFromString(String string, String delimiter) {
        String[] pieces = string.trim().toLowerCase().split(delimiter);
        float[] floats = new float[pieces.length];
        for (int i = 0; i < pieces.length; i++) {
            floats[i] = Float.parseFloat(pieces[i].trim());
        }
        return floats;
    }

    public static long[] parseLongsFromString(String string, String delimiter) {
        String[] pieces = string.trim().toLowerCase().split(delimiter);
        long[] longs = new long[pieces.length];
        for (int i = 0; i < pieces.length; i++) {
            longs[i] = Long.parseLong(pieces[i].trim());
        }
        return longs;
    }

    public static String getSDCardDirectory() {
        return Environment.getExternalStorageDirectory().getAbsolutePath();
    }

    public static String getDCIMDirectory() {
        return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath();
    }

    public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    public static int getScreenWidth() {
        return Resources.getSystem().getDisplayMetrics().widthPixels;
    }

    public static int getScreenHeight() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }

    public static int getCameraDisplayOrientation(Context context, int cameraId) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        int rotation = wm.getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;   // compensate the mirror
        } else {
            // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

    public static int createShaderProgram(String vss, String fss) {
        int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(vshader, vss);
        GLES20.glCompileShader(vshader);
        int[] status = new int[1];
        GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0);
        if (status[0] == 0) {
            Log.e(TAG, GLES20.glGetShaderInfoLog(vshader));
            GLES20.glDeleteShader(vshader);
            vshader = 0;
            return 0;
        }

        int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(fshader, fss);
        GLES20.glCompileShader(fshader);
        GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, status, 0);
        if (status[0] == 0) {
            Log.e(TAG, GLES20.glGetShaderInfoLog(fshader));
            GLES20.glDeleteShader(vshader);
            GLES20.glDeleteShader(fshader);
            fshader = 0;
            return 0;
        }

        int program = GLES20.glCreateProgram();
        GLES20.glAttachShader(program, vshader);
        GLES20.glAttachShader(program, fshader);
        GLES20.glLinkProgram(program);
        GLES20.glDeleteShader(vshader);
        GLES20.glDeleteShader(fshader);
        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0);
        if (status[0] == 0) {
            Log.e(TAG, GLES20.glGetProgramInfoLog(program));
            program = 0;
            return 0;
        }
        GLES20.glValidateProgram(program);
        GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, status, 0);
        if (status[0] == 0) {
            Log.e(TAG, GLES20.glGetProgramInfoLog(program));
            GLES20.glDeleteProgram(program);
            program = 0;
            return 0;
        }

        return program;
    }

    public static boolean isSupportedNPU() {
        String hardware = android.os.Build.HARDWARE;
        return hardware.equalsIgnoreCase("kirin810") || hardware.equalsIgnoreCase("kirin990");
    }

    public static Bitmap parseFileToBitmap(Context context,String img_file) {
        Bitmap image = null;
        try {
            if (!TextUtils.isEmpty(img_file)) {

                // Read test image file from custom path if the first character of mode path is '/', otherwise read test
                // image file from assets
                if (img_file.charAt(0) != '/') {
                    InputStream imageStream = context.getAssets().open(img_file);
                    image = BitmapFactory.decodeStream(imageStream);
                } else {
                    if (new File(img_file).exists()) {
                        image = BitmapFactory.decodeFile(img_file);
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }

    public static File saveBitmap(Bitmap bitmapUse) {
        Log.e("wy", "开始保存");
        //生成一个文件，存储我们将来拍照的照片
        String sdPath = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "/a1";
        File file = new File(sdPath);

        Log.e("wy","绝对文件路径: "+ file.getAbsoluteFile());
        Log.e("wy","文件名: "+ file.getName());
        if (!file.exists()) {
            file.mkdirs();
            Log.e("wy", "创建文件夹,路径："+file.getPath());
        }
        String mPath = System.currentTimeMillis() + "";
        Log.e("wy", "保存路径: " + sdPath);
        File f = new File(sdPath, mPath + ".jpg");
//        File f = new File("/sdcard/namecard/", picName);
        if (f.exists()) {
            f.delete();
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
//            10M
//            bitmapUse.compress(Bitmap.CompressFormat.PNG, 90, out);
//            0.5M
            bitmapUse.compress(Bitmap.CompressFormat.JPEG, 45, out);
            out.flush();
            out.close();
            Log.e("wy", "已经保存");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return f;
    }
}
